﻿using DotNet4.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Xml;
using WXBot.WXObject;

namespace WXBot
{
    public class WXWebAPI
    {
        /// <summary>
        /// http网络请求实施主体
        /// </summary>
        private HttpHelper httpClient = new HttpHelper();

        /// <summary>
        /// http请求详细信息，cookies保持者
        /// </summary>
        private HttpItem httpItem = new HttpItem();

        /// <summary>
        /// 首次获取到的登录二维码id
        /// </summary>
        private string qrUuid = "";

        public SendLogEvent LogEvent = null;

        public SendQrCodeImageEvent ImageEvent = null;

        /// <summary>
        /// 是否要终止获取消息的线程
        /// </summary>
        private bool isStop = false;

        /// <summary>
        /// 信息刷新的主机连接字符串
        /// </summary>
        private string Sync_host;

        /// <summary>
        /// 登录成功后获取到的重定向地址，使用一次
        /// </summary>
        private string redirect_uri = "";
        /// <summary>
        /// 获取当前所有请求的基础字符串，域名部分.带着前缀的
        /// </summary>
        private string base_uri = "";
        /// <summary>
        /// 获取的当前请求的主机域名，不带http前缀
        /// </summary>
        private string base_host = "";

        /// <summary>
        /// Uin,Sid,Skey,Pass_ticket.微信认真标志，认证完毕获取，以后交互时要使用
        /// </summary>
        private string Uin;
        private string Sid;
        private string Skey;
        private string Pass_ticket;

        /// <summary>
        /// 当前设备ID
        /// </summary>
        private string DeviceID;

        /// <summary>
        /// 当前验证数据字典，大多数post需要该字段
        /// </summary>
        private Dictionary<string, object> Base_request_obj;

        /// <summary>
        /// 登录成功后获取的返回值对象
        /// </summary>
        private WXInitRoot wxInitObj;

        /// <summary>
        /// 获取到的用户列表
        /// </summary>
        private WebWXMemberObject wxMemberObj;

        /// <summary>
        /// 获取到的群列表
        /// </summary>
        private WebWXGroupList GroupList;

        public WXWebAPI()
        {
            ///初始化设备ID及http引擎相关信息
            DeviceID = "e148376861764335";//'e' + getUTCMillTime(100);
            httpItem.Encoding = Encoding.UTF8;
            httpItem.UserAgent = "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5";
            httpItem.CookieCollection = new CookieCollection();

            ///获取所有的自定义回复内容
            SvaeWXMsgObj.GetAllAutoMsg();
        }

        /// <summary>
        /// 外部设置线程结束
        /// </summary>
        public void Stop()
        {
            isStop = true;
        }

        /// <summary>
        /// 外部调用开始工作
        /// </summary>
        public void Run()
        {
            //获取登录图片
            Image _image = getLoginQRCode();
            if (_image != null)
            {
                if (ImageEvent != null)
                {
                    ImageEvent(_image);
                }

                //等待用户确认登录
                if (isStop == false && WaitForUserLogin() == 200)
                {
                    //用户登录
                    if (login())
                    {
                        WriteLog("登录成功");
                        ///获取用户初始化消息
                        if(init())
                        {
                            ///反馈用户状态更改
                            status_notify();

                            ///获取联系人
                            if(get_contact())
                            {
                                WriteLog("获取用户列表成功");

                                ///消息守护
                                proc_msg();
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 通过get获取返回的html内容
        /// </summary>
        /// <param name="urlBase">基础连接地址</param>
        /// <param name="parms">要传递的参数</param>
        /// <returns>html内容</returns>
        private string getURLHTML(string urlBase, Dictionary<string, string> parms)
        {
            ///通过参数列表和基础地址构造请求地址
            StringBuilder builder = new StringBuilder();
            builder.Append(urlBase);
            if (parms != null && parms.Count > 0)
            {
                builder.Append("?");
                int i = 0;
                foreach (var item in parms)
                {
                    if (i > 0)
                        builder.Append("&");
                    builder.AppendFormat("{0}={1}", Uri.EscapeDataString(item.Key), Uri.EscapeDataString(item.Value));
                    i++;
                }
            }
            string strUlr = builder.ToString();
            if (string.IsNullOrEmpty(strUlr))
            {
                return "";
            }
            else
            {
                httpItem.URL = strUlr;
                httpItem.Method = "get";
                httpItem.ResultType = ResultType.String;

                ///获取网页内容，并返回
                HttpResult result = httpClient.GetHtml(httpItem);
                if (result.CookieCollection!=null&&result.CookieCollection.Count != 0)
                {
                    httpItem.CookieCollection.Add(result.CookieCollection);
                }
                return result.Html;
            }
        }

        /// <summary>
        /// 把Dictionary转化为json字符串
        /// </summary>
        /// <param name="dic">要转化的对象</param>
        /// <returns>json字符串</returns>
        private string DictionaryToJson(Dictionary<string, object> dic)
        {
            //实例化JavaScriptSerializer类的新实例  
            JavaScriptSerializer jss = new JavaScriptSerializer();
            try
            {
                return jss.Serialize(dic);
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// 通过post获取返回的html内容
        /// </summary>
        /// <param name="urlBase">基础连接地址</param>
        /// <param name="parms">要传递的参数</param>
        /// <returns>html内容</returns>
        private string postURLHTML(string urlBase, Dictionary<string, object> parms)
        {
            if (string.IsNullOrEmpty(urlBase))
            {
                return "";
            }
            else
            {

                httpItem.URL = urlBase;
                httpItem.Method = "post";
                httpItem.Postdata = DictionaryToJson(parms);
                httpItem.ResultType = ResultType.String;


                HttpResult result = httpClient.GetHtml(httpItem);
                if (result != null && result.CookieCollection != null && result.CookieCollection.Count != 0)
                {
                    httpItem.CookieCollection.Add(result.CookieCollection);
                }
                return result.Html;
            }
        }

        /// <summary>
        /// 获取UTC标准时差毫秒
        /// </summary>
        /// <returns>返回标准时间字符串</returns>
        private string getUTCMillTime(long n=10000)
        {
            DateTime dt = new DateTime(1970, 1, 1);
            return ((DateTime.UtcNow - dt).Ticks / n).ToString();
        }

        /// <summary>
        /// 获取请求的二维码图片
        /// </summary>
        /// <returns></returns>
        public Image getLoginQRCode()
        {
            ///构造请求参数表和基础地址
            Dictionary<string, string> _dic = new Dictionary<string, string>();
            _dic.Add("appid", StaticValues.uuid);
            _dic.Add("fun", "new");
            _dic.Add("lang", "zh_CN");
            _dic.Add("_", getUTCMillTime());

            //通过返回的Html内容获取imgID
            string html = getURLHTML("https://login.weixin.qq.com/jslogin", _dic);

            Regex reg = new Regex("window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\"");
            var resultreg = reg.Match(html).Groups;
            int code = 400;
            string imageID = "";
            if (resultreg.Count == 3)
            {
                try
                {
                    code = int.Parse(resultreg[1].ToString());
                }
                catch { }
                imageID = resultreg[2].ToString();
            }

            ///通过imgID获取二维码图片
            Image img = null;
            if (code == 200 && string.IsNullOrEmpty(imageID) == false)
            {
                string str = "https://login.weixin.qq.com/qrcode/{0}?t=webwx";
                str = string.Format(str, imageID);
                img = get_image(str);
                qrUuid = imageID;
            }

            return img;
        }

        /// <summary>
        /// 扫码后等待用户在手机上完成用户登录操作
        /// </summary>
        /// <returns>登录状态</returns>
        public int WaitForUserLogin()
        {
            string LOGIN_TEMPLATE = "https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip={0}&uuid={1}&_={2}";

            int tip = 1;
            int retry_time = 10;
            WriteLog("请使用手机微信扫描二维码");
            while (retry_time > 0 && isStop == false)
            {
                string url = string.Format(LOGIN_TEMPLATE, tip, qrUuid, getUTCMillTime());
                string html = getURLHTML(url, null);
                Regex reg = new Regex("window.code=(\\d+);");
                var resultreg = reg.Match(html).Groups;
                string codeStr = resultreg[1].ToString();
                switch (codeStr)
                {
                    case "201"://已扫描，未确认
                        WriteLog("二维码已扫描，等待确认");
                        tip = 0;
                        break;
                    case "200"://登录成功
                        Regex reg1 = new Regex("window.redirect_uri=\"(\\S+?)\";");
                        var resultreg1 = reg1.Match(html).Groups;
                        redirect_uri = resultreg1[1] + "&fun=new";
                        base_uri = redirect_uri.Substring(0, redirect_uri.LastIndexOf('/'));
                        base_host = base_uri.Substring(8, base_uri.IndexOf('/', 8)-8);
                        WriteLog("已经确认");
                        return 200;
                    case "408"://超时
                        WriteLog("等待超时，即将开始重新检查");
                        retry_time--;
                        break;
                    default:
                        retry_time--;
                        break;
                }
            }

            return -1;
        }

        /// <summary>
        /// 通过网络地址获取图片
        /// </summary>
        /// <param name="url">图片地址</param>
        /// <returns>图片对象</returns>
        private Image get_image(string url)
        {
            Image image = null;
            try
            {
                ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;  
                WebRequest webreq = WebRequest.Create(url);
                WebResponse webres = webreq.GetResponse();
                Stream stream = webres.GetResponseStream();
                image = System.Drawing.Image.FromStream(stream);
                stream.Close();
                stream.Dispose();
            }
            catch (Exception e)
            {
                return null;
            }
            return image;
        }

        private bool ValidateServerCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="_info">要记录的日志消息</param>
        private void WriteLog(string _info)
        {
            if (LogEvent != null)
            {
                LogEvent(_info);
            }
            else
            {
                Console.Write(_info);
            }
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <returns></returns>
        private bool login()
        {
            bool rs = false;

            if (redirect_uri.Length > 4)
            {
                //获取登录成功后反馈的重定向地址的内容
                string htmlstr = getURLHTML(redirect_uri, null);
                byte[] byteArray = Encoding.UTF8.GetBytes(htmlstr);
                MemoryStream stream = new MemoryStream(byteArray);

                XmlReaderSettings settings = new XmlReaderSettings();
                settings.IgnoreComments = true;//忽略文档里面的注释
                using (XmlReader reader = XmlReader.Create(stream, settings))
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(reader);
                    XmlNode xn = xmlDoc.SelectSingleNode("error");
                    foreach (XmlNode noneode in xn.ChildNodes)
                    {
                        if(noneode.Name == "skey")
                        {
                            Skey = noneode.ChildNodes[0].InnerText;
                        }
                        else if (noneode.Name == "wxsid")
                        {
                            Sid = noneode.ChildNodes[0].InnerText;
                        }
                        else if (noneode.Name == "wxuin")
                        {
                            Uin = noneode.ChildNodes[0].InnerText;
                        }
                        else if (noneode.Name == "pass_ticket")
                        {
                            Pass_ticket = noneode.ChildNodes[0].InnerText;
                        }
                    }

                    Base_request_obj = new Dictionary<string, object>();
                    Base_request_obj.Add("Uin", Uin);
                    Base_request_obj.Add("Sid", Sid);
                    Base_request_obj.Add("Skey", Skey);
                    Base_request_obj.Add("DeviceID", DeviceID);

                    rs = true;
                }
            }
            else
            {
                WriteLog("登录失败了");
            }

            return rs;
        }

        /// <summary>
        /// 初始化用户信息
        /// </summary>
        /// <returns></returns>
        private bool init()
        {
            bool rs = false;

            string initUrl = base_uri + string.Format("/webwxinit?r={0}&lang=en_US&pass_ticket={1}", getUTCMillTime(10000000), Pass_ticket);

            Dictionary<string, object> _dic = new Dictionary<string, object>();
            _dic.Add("BaseRequest", Base_request_obj);

            string htmlStr = postURLHTML(initUrl, _dic);

            JavaScriptSerializer jser = new JavaScriptSerializer();
            try
            {
                wxInitObj = jser.Deserialize<WXInitRoot>(htmlStr);
            }
            catch { }

            if (wxInitObj != null && wxInitObj.BaseResponse != null)
            {
                rs = wxInitObj.BaseResponse.Ret.Equals(0);
            }

            return rs;
        }

        /// <summary>
        /// 通过SyncKey数组获取一个认证字符串
        /// </summary>
        /// <returns></returns>
        private string Get_Sync_key_str()
        {
            string str = "";
            if (wxInitObj != null && wxInitObj.SyncKey != null && wxInitObj.SyncKey.List != null)
            {
                foreach (var oneitem in wxInitObj.SyncKey.List)
                {
                    if (string.IsNullOrEmpty(str))
                    {
                        str += oneitem.Key.ToString() + "_" + oneitem.Val.ToString();
                    }
                    else
                    {
                        str += "|" + oneitem.Key.ToString() + "_" + oneitem.Val.ToString();
                    }
                }
            }
            return str;
        }

        /// <summary>
        /// 用户状态更改请求
        /// </summary>
        /// <returns></returns>
        private bool status_notify()
        {
            bool rs = false;
            string status_notify_Url = base_uri + @"/webwxstatusnotify?lang=zh_CN&pass_ticket=" + Pass_ticket;

            Dictionary<string, object> _dic = new Dictionary<string, object>();
            _dic.Add("BaseRequest", Base_request_obj);
            _dic.Add("Code", 3);
            _dic.Add("FromUserName", wxInitObj.User.UserName);
            _dic.Add("ToUserName", wxInitObj.User.UserName);
            _dic.Add("ClientMsgId", getUTCMillTime(10000000));

            string htmlStr = postURLHTML(status_notify_Url, _dic);

            JavaScriptSerializer jser = new JavaScriptSerializer();
            WXInitRoot curObj = null;
            try
            {
                curObj = jser.Deserialize<WXInitRoot>(htmlStr);
            }
            catch { }

            if (curObj != null && curObj.BaseResponse != null)
            {
                rs = curObj.BaseResponse.Ret.Equals(0);
            }

            return rs;
        }

        /// <summary>
        /// 获取联系人请求
        /// </summary>
        /// <returns></returns>
        private bool get_contact()
        {
            bool rs = false;
            string get_contact_Url = base_uri + "/webwxgetcontact?pass_ticket={0}&skey={1}&r={2}";
            get_contact_Url = string.Format(get_contact_Url, Pass_ticket, Skey, getUTCMillTime(10000000));

            Dictionary<string, object> _dic = new Dictionary<string, object>();
            string htmlStr = postURLHTML(get_contact_Url, _dic);

            JavaScriptSerializer jser = new JavaScriptSerializer();
            try
            {
                wxMemberObj = jser.Deserialize<WebWXMemberObject>(htmlStr);
            }
            catch { }

            if (wxMemberObj != null && wxMemberObj.BaseResponse != null)
            {
                wxMemberObj.SortMembers();
                rs = wxMemberObj.BaseResponse.Ret.Equals(0);
            }

            batch_get_group_members();

            return rs;
        }

        /// <summary>
        /// 用户消息处理
        /// </summary>
        private void proc_msg()
        {
            ///第一次向服务器检查消息
            test_sync_check();

            while(true)
            {
                ///如果线程要结束，就退出
                if(isStop)
                {
                    break;
                }

                ///计时开始
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start(); 

                ///循环检查有没有消息
                int[] rs = sync_check();
                if (rs[0] == 1100)// 从微信客户端上登出
                {
                    WriteLog("从微信客户端上登出");
                    break;
                }
                else if (rs[0] == 1101)// 从其它设备上登了网页微信
                {
                    WriteLog("从其它设备上登了网页微信");
                    break;
                }
                else if (rs[0] == 1102)// 从其它设备上登了网页微信
                {
                    WriteLog("登陆的信息出现错误了,需要重新登陆一次了");
                    break;
                }
                else if (rs[0] == 0)///如果有消息就处理
                {
                    switch(rs[1])
                    {
                        case 0://"无事件"
                            break;
                        case 2://"有新消息"
                        case 3://"未知"
                        case 4://"通讯录更新"
                        case 6://"可能是红包"
                        case 7://"在手机上操作了微信"
                        default:
                            WXBot.WXObject.WXMsgObj.WebWXSyncObj msgObj = sync();
                            if(msgObj != null)
                            {
                                handle_msg(msgObj);
                            }
                            break;
                    }
                }
                else
                {
                    WriteLog("获得未知消息");
                }

                ///计时结束，如果不够一秒，那就等等，防止被弄
                stopwatch.Stop(); 
                TimeSpan timespan = stopwatch.Elapsed; 
                if(timespan.Milliseconds < 800)
                {
                    System.Threading.Thread.Sleep(1000-timespan.Milliseconds);
                }
            }
        }

        /// <summary>
        /// 第一次扫描事件
        /// </summary>
        /// <returns></returns>
        private bool test_sync_check()
        {
            bool rs = false;

            ///判断哪个连接可用，并执行一次扫描
            string[] hostlist = new string[] { "webpush.", "webpush2." };
            foreach (string hoststr in hostlist)
            {
                Sync_host = hoststr + base_host;
                if(sync_check()[0]==0)
                {
                    rs = true;
                    break;
                }
            }

            return rs;
        }

        /// <summary>
        /// 向服务器进行消息扫描
        /// </summary>
        /// <returns></returns>
        private int[] sync_check()
        {
            int[] rs = new int[]{-1,-1};

            Dictionary<string, string> _parmDic = new Dictionary<string, string>();
            _parmDic.Add("r", getUTCMillTime(10000000));
            _parmDic.Add("sid", Sid);
            _parmDic.Add("uin", Uin);
            _parmDic.Add("skey", Skey);
            _parmDic.Add("deviceid", DeviceID);
            _parmDic.Add("synckey", Get_Sync_key_str());
            _parmDic.Add("_", getUTCMillTime(10000000));

            string url = "https://" + Sync_host + "/cgi-bin/mmwebwx-bin/synccheck";

            string htmlstr = getURLHTML(url, _parmDic);

            //window.synccheck={retcode:\"0\",selector:\"2\"}
            Regex reg = new Regex("window.synccheck={retcode:\"(\\d+)\",selector:\"(\\d+)\"}");
            var resultreg = reg.Match(htmlstr).Groups;
            if (resultreg.Count == 3)
            {
                try
                {
                    rs[0] = int.Parse(resultreg[1].ToString());
                    rs[1] = int.Parse(resultreg[2].ToString());
                }
                catch { }
            }

            return rs;
        }

        /// <summary>
        /// 获取服务器当前产生的消息
        /// </summary>
        /// <returns>消息对象</returns>
        private WXBot.WXObject.WXMsgObj.WebWXSyncObj sync()
        {
            string sync_url = base_uri + "/webwxsync?sid={0}&skey={1}&lang=en_US&pass_ticket={2}";
            sync_url = string.Format(sync_url,Sid,Skey,Pass_ticket);
            
            Dictionary<string, object> _dic = new Dictionary<string, object>();
            _dic.Add("BaseRequest", Base_request_obj);
            _dic.Add("SyncKey", wxInitObj.SyncKey);
            _dic.Add("rr",~long.Parse(getUTCMillTime(10000000)));

            string htmlStr = postURLHTML(sync_url, _dic);

            JavaScriptSerializer jser = new JavaScriptSerializer();
            WXBot.WXObject.WXMsgObj.WebWXSyncObj wxMsgObj = null;
            try
            { 
            wxMsgObj=jser.Deserialize<WXBot.WXObject.WXMsgObj.WebWXSyncObj>(htmlStr);
                 }catch  { }
            ///用当前的SyncKey替换已有的SyncKey，保证下次扫描消息获取的不是重复消息
            if (wxMsgObj != null && wxMsgObj.BaseResponse != null&&wxMsgObj.BaseResponse.Ret.Equals(0))
            {
                wxInitObj.SyncKey = wxMsgObj.SyncKey;
            }

            return wxMsgObj;
        }

        MemberObj fengduiUser = null;

        /// <summary>
        /// 自己的消息处理函数
        /// </summary>
        /// <param name="msgObj">要进行处理的消息</param>
        private void handle_msg(WXBot.WXObject.WXMsgObj.WebWXSyncObj msgObj)
        {
            if(msgObj.AddMsgCount != 0 && msgObj.AddMsgList!= null)
            {
                foreach(WXBot.WXObject.WXMsgObj.AddMsgList oneMsg in msgObj.AddMsgList)
                {
                    MemberObj fUser = findMemberInfoById(oneMsg.FromUserName);

                    string msgInfo = "收到{0}的消息:{1}";
                    if (fUser != null)
                    {
                        msgInfo = string.Format(msgInfo, fUser.NickName, oneMsg.Content);
                    }
                    else
                    {
                        msgInfo = string.Format(msgInfo, oneMsg.FromUserName, oneMsg.Content);
                    }
                    WriteLog(msgInfo);

                    //区分消息
                    WXMsg rs = GetWXMsgFormOriMsg(oneMsg);

                    if (rs!= null && string.IsNullOrEmpty(rs.From)==false)
                    {
                        ///保存消息
                        SvaeWXMsgObj.DoSave(rs);

                        //威信的消息转发给dd
                        //SendMsgToDDClass.SendMsg2DD(rs);

                        //对于需要自动回复的消息进行处理
                        Auto_msg(oneMsg, rs);
                    }
                }
            }
        }

        /// <summary>
        /// 通过用户id获取用户信息
        /// </summary>
        /// <param name="_userId">用户id</param>
        /// <returns>用户详细信息</returns>
        private MemberObj findMemberInfoById(string _userId)
        {
            if(wxMemberObj != null && wxMemberObj.MemberList != null)
            {
                foreach(MemberObj oneUser in wxMemberObj.MemberList)
                {
                    if(oneUser.UserName.Equals(_userId))
                    {
                        return oneUser;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 请求群用户信息
        /// </summary>
        private void batch_get_group_members()
        {
            string batch_get_group_members_Url = base_uri + @"/webwxbatchgetcontact?type=ex&r={0}&pass_ticket={1}";
            batch_get_group_members_Url = string.Format(batch_get_group_members_Url,getUTCMillTime(10000000),Pass_ticket);
            
            Dictionary<string, object> _dic = new Dictionary<string, object>();
            _dic.Add("BaseRequest", Base_request_obj);
            _dic.Add("Count", wxMemberObj.GroupMember.Count);

            List<object> allGroupList = new List<object>();
            foreach(MemberObj oneGroup in wxMemberObj.GroupMember)
            {
                if(oneGroup.NickName.Equals("粪堆"))
                {
                    fengduiUser = oneGroup;
                }
                Dictionary<string, object> _dicOneGroup = new Dictionary<string, object>();
                _dicOneGroup.Add("UserName", oneGroup.UserName);
                _dicOneGroup.Add("EncryChatRoomId", "");
                allGroupList.Add(_dicOneGroup);
            }
            _dic.Add("List", allGroupList);

            string htmlStr = postURLHTML(batch_get_group_members_Url, _dic);

            JavaScriptSerializer jser = new JavaScriptSerializer();
            try
            {
                GroupList = jser.Deserialize<WebWXGroupList>(htmlStr);
            }
            catch { }

            if (GroupList != null && GroupList.BaseResponse != null)
            {
                //rs = curObj.BaseResponse.Ret.Equals(0);
            }
        }

        /// <summary>
        /// 从原始消息得到我们想要的消息类型
        /// </summary>
        /// <param name="oneMsg">原始消息</param>
        /// <returns>重新封装的消息</returns>
        private WXMsg GetWXMsgFormOriMsg(WXBot.WXObject.WXMsgObj.AddMsgList oneMsg)
        {
            if (string.IsNullOrEmpty(oneMsg.FromUserName) == false)
            {
                WXMsg rs = new WXMsg();
                if (oneMsg.FromUserName.IndexOf("@@") == 0)///群
                {
                    foreach(var oneGroup in GroupList.ContactList)
                    {
                        if(oneGroup.UserName.Equals(oneMsg.FromUserName))
                        {
                            rs.From = oneGroup.GetDisName();
                            int ntemp = oneMsg.Content.IndexOf(":");
                            if (ntemp != -1)///群里面的正常消息，Content结构为"用户ID:消息内容"
                            {
                                string usrNameStr = oneMsg.Content.Substring(0, ntemp);
                                oneMsg.Content = oneMsg.Content.Substring(ntemp + 1);
                                foreach (var oneUser in oneGroup.MemberList)
                                {
                                    if (oneUser.UserName.Equals(usrNameStr))
                                    {
                                        rs.From2 = oneUser.GetDisName();
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                else if (oneMsg.FromUserName.IndexOf("@") == 0)///一般用户消息
                {
                    foreach(var oneUser in wxMemberObj.MemberList)
                    {
                        if (oneUser.UserName.Equals(oneMsg.FromUserName))
                        {
                            rs.From = oneUser.GetDisName();
                            break;
                        }
                    }
                }
                else if (string.IsNullOrEmpty(rs.From))
                {
                    rs.From = oneMsg.FromUserName;
                }

                ///消息内容解析
                getMessgeContent(oneMsg, rs);
                rs.Type = oneMsg.MsgType;
                if(oneMsg.MsgType == 49 && oneMsg.AppMsgType==8)
                {
                    rs.Type = 3;
                }
                rs.Time = DateTime.Now;

                return rs;
            }
            return null;
        }

        /// <summary>
        /// 解析消息内容
        /// </summary>
        /// <param name="msg">原始消息</param>
        /// <param name="oneMsg">解析后的消息</param>
        private void getMessgeContent( WXBot.WXObject.WXMsgObj.AddMsgList msg, WXMsg oneMsg)
        {
            if(string.IsNullOrEmpty(msg.FromUserName))
            {
                return;
            }
            string str = msg.Content;

            switch (msg.MsgType)
            {
                case 1://文本消息
                    if (msg.SubMsgType==48)//位置信息
                    {
                        str = msg.OriContent;
                        oneMsg.Url = URLDecode(msg.Url);
                    }
                    else
                    {
                        str = msg.Content.Replace("<br/>", "");
                    }
                    break;
                case 3://图片消息
                case 47://动画表情
                    string imageUrl = base_uri + @"/webwxgetmsgimg?msgid={0}&skey={1}";
                    imageUrl = string.Format(imageUrl, msg.MsgId, Skey);
                    str = saveURLHTMLObject(imageUrl, 3);
                    if (string.IsNullOrEmpty(str))
                    {
                        str = "系统表情无法获取";
                    }
                    break;
                case 34://语音消息
                    string voiceUrl = base_uri + @"/webwxgetvoice?msgid={0}&skey={1}";
                    voiceUrl = string.Format(voiceUrl, msg.MsgId, Skey);
                    str = saveURLHTMLObject(voiceUrl, 34);
                    break;
                case 49://分享
                    //str = msg.FileName;
                    //oneMsg.Url = URLDecode(msg.Url);
                    str = Get49Msg(msg, oneMsg);
                    break;
                case 43://小视频
                case 62://小视频
                    string videoUrl = base_uri + @"/webwxgetvideo?msgid={0}&skey={1}&type=flv";
                    videoUrl = string.Format(videoUrl, msg.MsgId, Skey);
                    str = saveURLHTMLObject(videoUrl, 62);
                    break;
                default:
                    str = msg.Content;
                    break;
            }

            oneMsg.Msg = str;
        }

        private string Get49Msg(WXBot.WXObject.WXMsgObj.AddMsgList msg, WXMsg oneMsg)
        {
            string str = msg.Content;
            if (msg.AppMsgType == 8)
            {
                string imageUrl = base_uri + @"/webwxgetmsgimg?msgid={0}&skey={1}";
                imageUrl = string.Format(imageUrl, msg.MsgId, Skey);
                str = saveURLHTMLObject(imageUrl, 3);
                if (string.IsNullOrEmpty(str))
                {
                    str = "系统表情无法获取";
                }
            }
            else
            {
                str = msg.FileName;
                oneMsg.Url = URLDecode(msg.Url);
            }
            return str;
            //    rawMsg = m
            //    cookiesList = { name: data for name, data in core.s.cookies.items()}
            //def download_atta(attaDir = None):
            //        url = core.loginInfo['fileUrl'] + '/webwxgetmedia'
            //        params = {
            //    'sender': rawMsg['FromUserName'],
            //            'mediaid': rawMsg['MediaId'],
            //            'filename': rawMsg['FileName'],
            //            'fromuser': core.loginInfo['wxuin'],
            //            'pass_ticket': 'undefined',
            //            'webwx_data_ticket': cookiesList['webwx_data_ticket'],}
            //headers = { 'User-Agent' : config.USER_AGENT }
            //r = core.s.get(url, params=params, stream = True, headers = headers)
            //        tempStorage = io.BytesIO()
            //        for block in r.iter_content(1024):
            //            tempStorage.write(block)
            //        if attaDir is None:
            //            return tempStorage.getvalue()
            //        with open(attaDir, 'wb') as f:
            //            f.write(tempStorage.getvalue())
            //        return ReturnValue({
            //    'BaseResponse': {
            //        'ErrMsg': 'Successfully downloaded',
            //            'Ret': 0, }
            //})
            //    msg = {
            //    'Type': 'Attachment',
            //        'Text': download_atta, }
            //elif m['AppMsgType'] == 8:
            //    download_fn = get_download_fn(core,
            //        '%s/webwxgetmsgimg' % core.loginInfo['url'], m['NewMsgId'])
            //    msg = {
            //    'Type'     : 'Picture',
            //        'FileName' : '%s.gif' % (
            //            time.strftime('%y%m%d-%H%M%S', time.localtime())),
            //        'Text'     : download_fn, }
            //elif m['AppMsgType'] == 17:
            //    msg = {
            //    'Type': 'Note',
            //        'Text': m['FileName'], }
            //elif m['AppMsgType'] == 2000:
            //    regx = r'\[CDATA\[(.+?)\][\s\S]+?\[CDATA\[(.+?)\]'
            //    data = re.search(regx, m['Content'])
            //    if data:
            //        data = data.group(2).split(u'\u3002')[0]
            //    else:
            //        data = 'You may found detailed info in Content key.'
            //    msg = {
            //    'Type': 'Note',
            //        'Text': data, }
            //else:
            //    msg = {
            //    'Type': 'Sharing',
            //        'Text': m['FileName'], }
        }

        /// <summary>
        /// 根据类别保存连接对象内容到本地
        /// </summary>
        /// <param name="urlBase">请求连接</param>
        /// <param name="msgType">类型</param>
        /// <returns>保存地址</returns>
        private string saveURLHTMLObject(string urlBase, int msgType)
        {
            try
            {
                string strUlr = urlBase;
                if (string.IsNullOrEmpty(strUlr))
                {
                    return "";
                }
                else
                {
                    httpItem.URL = strUlr;
                    httpItem.Method = "get";
                    httpItem.ResultType = ResultType.Byte;

                    HttpResult result = httpClient.GetHtml(httpItem);
                    if (result.CookieCollection != null && result.CookieCollection.Count != 0)
                    {
                        httpItem.CookieCollection.Add(result.CookieCollection);
                    }

                    if (result.ResultByte != null)
                    {
                        using (Stream stream = new MemoryStream(result.ResultByte))
                        {
                            stream.Write(result.ResultByte, 0, result.ResultByte.Length);
                            String str = "";

                            if (msgType == 3 || msgType == 47 ||msgType==8)
                            {
                                Image image = Image.FromStream(stream);
                                if (image != null)
                                {
                                    string exName = GetImageExtension(image);
                                    str = @"\image\" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + "." + exName;
                                    image.Save(System.Environment.CurrentDirectory + str, image.RawFormat);
                                }
                            }
                            else if (msgType == 34)
                            {
                                str = @"\voice\" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".mp3";
                                File.WriteAllBytes(System.Environment.CurrentDirectory + str, result.ResultByte);
                            }
                            else if (msgType == 62)
                            {
                                str = @"\video\" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".flv";
                                File.WriteAllBytes(System.Environment.CurrentDirectory + str, result.ResultByte);
                            }

                            return str;
                        }
                    }

                    return "";
                }
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 根据图形获取图形的扩展名 
        /// </summary>
        /// <param name="p_Image">图形</param>
        /// <returns>扩展名</returns>
        private string GetImageExtension(Image p_Image)
        {
            Type Type = typeof(System.Drawing.Imaging.ImageFormat);
            System.Reflection.PropertyInfo[] _ImageFormatList = Type.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            for (int i = 0; i != _ImageFormatList.Length; i++)
            {
                System.Drawing.Imaging.ImageFormat _FormatClass = (System.Drawing.Imaging.ImageFormat)_ImageFormatList[i].GetValue(null, null);
                if (_FormatClass.Guid.Equals(p_Image.RawFormat.Guid))
                {
                    return _ImageFormatList[i].Name;
                }
            }
            return "";
        }

        /// <summary>
        /// 自动回复消息
        /// </summary>
        /// <param name="msgObj">当前收到的原始消息</param>
        /// <param name="rs">处理过的消息</param>
        private void Auto_msg(WXBot.WXObject.WXMsgObj.AddMsgList msgObj, WXMsg rs)
        {
            if(msgObj != null && rs != null && string.IsNullOrEmpty(rs.From)==false && string.IsNullOrEmpty(msgObj.FromUserName)==false)
            {
                /// 根据全部变量内容判断是否要对当前消息进行回复
                if(SvaeWXMsgObj.AllAutoMsg != null && SvaeWXMsgObj.AllAutoMsg.ContainsKey(rs.Msg))
                {
                    string get_contact_Url = base_uri + "/webwxsendmsg?pass_ticket={0}";
                    get_contact_Url = string.Format(get_contact_Url, Pass_ticket);

                    Dictionary<string, object> _dicmsg = new Dictionary<string, object>();
                    _dicmsg.Add("Type", 1);
                    _dicmsg.Add("Content", SvaeWXMsgObj.AllAutoMsg[rs.Msg]);
                    _dicmsg.Add("FromUserName", wxInitObj.User.UserName);
                    _dicmsg.Add("ToUserName", msgObj.FromUserName);
                    string idss = getUTCMillTime(1);
                    _dicmsg.Add("LocalID", idss);
                    _dicmsg.Add("ClientMsgId", idss);

                    Dictionary<string, object> _dic = new Dictionary<string, object>();
                    _dic.Add("BaseRequest", Base_request_obj);
                    _dic.Add("Msg", _dicmsg);
                    _dic.Add("Scene", 0);

                    httpItem.PostEncoding = Encoding.UTF8;

                    string htmlStr = postURLHTML(get_contact_Url, _dic);

                    httpItem.PostEncoding = null;
                }
            }
        }

        public void SendMsg(string msg, string touser)
        {
            string get_contact_Url = base_uri + "/webwxsendmsg?pass_ticket={0}";
            get_contact_Url = string.Format(get_contact_Url, Pass_ticket);

            Dictionary<string, object> _dicmsg = new Dictionary<string, object>();
            _dicmsg.Add("Type", 1);
            _dicmsg.Add("Content", msg);
            _dicmsg.Add("FromUserName", wxInitObj.User.UserName);
            _dicmsg.Add("ToUserName", touser);
            string idss = getUTCMillTime(1);
            _dicmsg.Add("LocalID", idss);
            _dicmsg.Add("ClientMsgId", idss);

            Dictionary<string, object> _dic = new Dictionary<string, object>();
            _dic.Add("BaseRequest", Base_request_obj);
            _dic.Add("Msg", _dicmsg);
            _dic.Add("Scene", 0);

            httpItem.PostEncoding = Encoding.UTF8;

            string htmlStr = postURLHTML(get_contact_Url, _dic);

            httpItem.PostEncoding = null;
        }

        public void SendMsgToFD(string msg)
        {
            SendMsg(msg, fengduiUser.UserName);
        }


        /// <summary>
        /// 对消息内的连接进行转义替换
        /// </summary>
        /// <param name="url">原始连接</param>
        /// <returns>转义字符替换后的连接</returns>
        private string URLDecode(string url)
        {
            url = url.Replace("&quot;","\"");
            url = url.Replace("&amp;","&");
            url = url.Replace("&lt;","<");
            url = url.Replace("&gt;",">");
            url = url.Replace("&nbsp;"," ");
            return url;
        }

        /// <summary>
        /// 外部可以调用的增加自定义回复消息的接口
        /// </summary>
        /// <param name="remsg"></param>
        /// <param name="sendmsg"></param>
        public void AddAutoMsg(string remsg,string sendmsg)
        {
            SvaeWXMsgObj.AllAutoMsg.Add(remsg, sendmsg);
            SvaeWXMsgObj.InsertOneAutoMsg(remsg, sendmsg);
        }
    }
}
